home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 11 / Mac Magazin and MacEasy Magazine CD - Issue 11.iso / Sharewarebibliothek / Entwickler / appe Windows 2.0 / floaters.c < prev    next >
Text File  |  1995-06-11  |  10KB  |  304 lines

  1. // File "floaters.c" - 
  2.  
  3. #include <GestaltEqu.h>
  4. #include <TextServices.h>
  5.  
  6. #include "floaters.h"
  7. #include "main.h"
  8.  
  9. // * ****************************************************************************** *
  10. // Global Declarations
  11.  
  12. extern GlobalsRec glob;
  13.  
  14. // * ****************************************************************************** *
  15. // * ****************************************************************************** *
  16.  
  17. WindowPtr NewFloater(Ptr wStorage, Rect *bounds, Str255 title, Boolean visFlag,
  18.         short wdefProc, WindowPtr behind, Boolean closeFlag, long refCon, long hotApp,
  19.         FloaterEventProcPtr eventHandler, FloaterCloseProcPtr closeHandler) {
  20.     short err=0;
  21.     Boolean myStorage = (wStorage) ? TRUE : FALSE;
  22.     WindowPtr win=0;
  23.     FloaterQElemPtr myQElem;
  24.     
  25.     if (myStorage) wStorage = NewPtr(sizeof(WindowRecord));
  26.     if (myStorage && !wStorage) return(0);
  27.     
  28.     err = NewServiceWindow(wStorage, bounds, title, FALSE, wdefProc, (WindowPtr) -1,
  29.             closeFlag, (ComponentInstance) kCurrentProcess, &win);
  30.     if (err) {
  31.         if (myStorage) DisposePtr(wStorage);
  32.         return(0);
  33.         }
  34.         
  35.     myQElem = (FloaterQElemPtr) NewPtrSys(sizeof(* myQElem));
  36.     if (! myQElem) {
  37.         if (win) CloseServiceWindow(win);
  38.         if (myStorage) DisposePtr(wStorage);
  39.         return(0);
  40.         }
  41.     myQElem->qLink = 0;
  42.     myQElem->qType = 0;
  43.     myQElem->hideMe = FALSE;
  44.     myQElem->hotApplication = hotApp;
  45.     myQElem->floatWindow = win;
  46.     myQElem->eventHandler = eventHandler;
  47.     myQElem->closeHandler = closeHandler;
  48.     Enqueue((QElem *) myQElem, &glob.allFloatWindows);
  49.  
  50.     SetWRefCon(win, refCon);
  51.     HiliteWindow(win, -1);
  52.     if (visFlag) ShowHideFloater(win);
  53.  
  54.     return(win);
  55.     }
  56.  
  57. // * ****************************************************************************** *
  58. // * ****************************************************************************** *
  59.  
  60. void CloseFloater(WindowPtr win) {
  61.     FloaterQElemPtr myQElem, qTail;
  62.     
  63.     // Get the window's QElem and release its memory
  64.     myQElem = GetOneFloater(win, TRUE);
  65.     if (myQElem) DisposePtr((Ptr) myQElem);
  66.     
  67.     ShowHide(win, 0);
  68.     CloseServiceWindow(win);
  69.  
  70.     UpdateFloater(0);
  71.     }
  72.  
  73. // * ****************************************************************************** *
  74. // * ****************************************************************************** *
  75.  
  76. void DisposeFloater(WindowPtr win) {
  77.     FloaterQElemPtr myQElem;
  78.     
  79.     // Get the window's QElem and release its memory
  80.     myQElem = GetOneFloater(win, TRUE);
  81.     if (myQElem) DisposePtr((Ptr) myQElem);
  82.     
  83.     ShowHide(win, 0);
  84.     CloseServiceWindow(win);
  85.     DisposePtr((Ptr) win);
  86.     
  87.     UpdateFloater(0);
  88.     }
  89.  
  90. // * ****************************************************************************** *
  91. // * ****************************************************************************** *
  92.  
  93. FloaterQElemPtr GetOneFloater(WindowPtr win, Boolean dequeueIt) {
  94.     FloaterQElemPtr myQElem;
  95.     
  96.     // Get the window's QElem and release its memory
  97.     if (glob.allFloatWindows.qTail) glob.allFloatWindows.qTail->qLink = 0;
  98.     for(myQElem = (FloaterQElemPtr) glob.allFloatWindows.qHead; myQElem && 
  99.             (myQElem->floatWindow != win); myQElem = myQElem->qLink);
  100.  
  101.     if (dequeueIt && myQElem) Dequeue((QElem *) myQElem, &glob.allFloatWindows);
  102.     return(myQElem);
  103.     }
  104.  
  105. // * ****************************************************************************** *
  106. // * ****************************************************************************** *
  107.  
  108. FloaterQElemPtr GetIndFloater(short index, Boolean dequeueIt) {
  109.     FloaterQElemPtr myQElem;
  110.     
  111.     if (index <= 0) return(0);
  112.     
  113.     // Get the window's QElem and release its memory
  114.     if (glob.allFloatWindows.qTail) glob.allFloatWindows.qTail->qLink = 0;
  115.     for(myQElem = (FloaterQElemPtr) glob.allFloatWindows.qHead, index--;
  116.             myQElem && index; myQElem = myQElem->qLink, index--);
  117.  
  118.     if (dequeueIt && myQElem) Dequeue((QElem *) myQElem, &glob.allFloatWindows);
  119.     return(myQElem);
  120.     }
  121.  
  122. // * ****************************************************************************** *
  123. // * ****************************************************************************** *
  124.  
  125. // If you have set the Hot Application, then this function checks whether that
  126. //   process is the front one and hides or shows the window as appropriate.
  127. Boolean ShowHideFloater(WindowPtr win) {
  128.     Boolean toHide, anyChanges=FALSE;
  129.     short index;
  130.     ProcessSerialNumber psn;
  131.     ProcessInfoRec pInfo;
  132.     FloaterQElemPtr myQElem;
  133.     
  134.     pInfo.processInfoLength = sizeof(pInfo);
  135.     pInfo.processName = 0;
  136.     pInfo.processAppSpec = 0;
  137.     
  138.     if (GetFrontProcess(&psn) || GetProcessInformation(&psn, &pInfo)) 
  139.         pInfo.processSignature = -1;
  140.  
  141.     if (! win) {
  142.         for(myQElem = GetIndFloater(index = 1, FALSE); myQElem; 
  143.                 myQElem = GetIndFloater(++index, FALSE)) {
  144.             win = myQElem->floatWindow;
  145.             if (! win) continue;
  146.  
  147.             toHide = glob.hideFloats || glob.blockFloats || glob.modalFloats || 
  148.                     myQElem->hideMe || (myQElem->hotApplication && 
  149.                     (pInfo.processSignature != myQElem->hotApplication));
  150.             
  151.             if (! toHide && ! ((WindowPeek) win)->visible) {
  152.                 ShowHide(win, TRUE);
  153.                 anyChanges = TRUE;
  154.                 }
  155.               else if (toHide && ((WindowPeek) win)->visible) {
  156.                 ShowHide(win, FALSE);
  157.                 anyChanges = TRUE;
  158.                 }
  159.             }
  160.         }
  161.       else if (myQElem = GetOneFloater(win, FALSE)) {
  162.         toHide = glob.hideFloats || glob.blockFloats || glob.modalFloats || 
  163.                 myQElem->hideMe || (myQElem->hotApplication && 
  164.                 (pInfo.processSignature != myQElem->hotApplication));
  165.         
  166.         if (! toHide && ! ((WindowPeek) win)->visible) {
  167.             ShowHide(win, TRUE);
  168.             anyChanges = TRUE;
  169.             }
  170.           else if (toHide && ((WindowPeek) win)->visible) {
  171.             ShowHide(win, FALSE);
  172.             anyChanges = TRUE;
  173.             }
  174.         }
  175.     return(anyChanges);
  176.     }
  177.  
  178. // * ****************************************************************************** *
  179. // * ****************************************************************************** *
  180.  
  181. void UpdateFloater(WindowPtr win) {
  182.     short index;
  183.     EventRecord theEvent;
  184.     FloaterQElemPtr myQElem;
  185.  
  186.     theEvent.what = updateEvt;
  187.     theEvent.when = TickCount();
  188.     theEvent.message = (long) win;
  189.     
  190.     if (! win) {
  191.         // Call the event handler for every floating window
  192.         for(myQElem = GetIndFloater(index = 1, FALSE); myQElem; 
  193.                 myQElem = GetIndFloater(++index, FALSE)) {
  194.             win = myQElem->floatWindow;
  195.             if (win && ! EmptyRgn(((WindowPeek) win)->updateRgn)) {
  196.                 theEvent.message = (long) win;
  197.                 if (myQElem->eventHandler) (*myQElem->eventHandler)(&theEvent, win);
  198.                 }
  199.             }
  200.         }
  201.       else if (myQElem = GetOneFloater(win, FALSE))
  202.         // Call the event handler for the indicated window
  203.         if (! EmptyRgn(((WindowPeek) win)->updateRgn))
  204.             if (myQElem->eventHandler) (*myQElem->eventHandler)(&theEvent, win);
  205.  
  206.     }
  207.  
  208. // * ****************************************************************************** *
  209. // * ****************************************************************************** *
  210.  
  211. void EventDispatchFloaters(EventRecord *theEvent, WindowPtr win) {
  212.     short index;
  213.     FloaterQElemPtr myQElem;
  214.  
  215.     if (! win) {
  216.         // Call the event handler for every floating window
  217.         for(myQElem = GetIndFloater(index = 1, FALSE); myQElem; 
  218.                 myQElem = GetIndFloater(++index, FALSE)) 
  219.             if (myQElem->eventHandler) 
  220.                 (*myQElem->eventHandler)(theEvent, myQElem->floatWindow);
  221.         }
  222.       else if (myQElem = GetOneFloater(win, FALSE))
  223.         // Call the event handler for the indicated window
  224.         if (myQElem->eventHandler) 
  225.             (*myQElem->eventHandler)(theEvent, myQElem->floatWindow);
  226.  
  227.     }
  228.  
  229.  
  230. // * ****************************************************************************** *
  231. // * ****************************************************************************** *
  232.  
  233. void CloseRemainingFloaters() {
  234.     FloaterQElemPtr myQElem;
  235.  
  236.     // For each tracked window, we call its close procedure - WE'RE QUITTING
  237.     //   Of course, you may find it necessary to add a "Save?" dialog, and escape
  238.     //   the quit sequence on a user cancel -- this code would need to be fixed.
  239.     while(myQElem = GetIndFloater(1, FALSE)) 
  240.         if (myQElem->closeHandler) (*myQElem->closeHandler)(myQElem->floatWindow);
  241.           else DisposeFloater(myQElem->floatWindow);
  242.     }
  243.  
  244. // * ****************************************************************************** *
  245. // * ****************************************************************************** *
  246.  
  247. Boolean GetFloaterEvent(EventRecord *theEvent) {
  248.     Boolean floaterEvent = FALSE;
  249.     short err=0, index;
  250.     EvQEl *fwdEvent=0;
  251.     FloaterQElemPtr myQElem;
  252.     
  253.     // Extract any forwarded events... and treat them as normal
  254.     if (fwdEvent = (EvQEl *) glob.forwardedEvents.qHead)
  255.         err = Dequeue((QElemPtr) fwdEvent, &glob.forwardedEvents);
  256.  
  257.     if (fwdEvent && !err) {
  258.         BlockMove(&fwdEvent->evtQWhat, theEvent, sizeof(EventRecord));
  259.         DisposePtr((Ptr) fwdEvent);
  260.         
  261.         // DONT ZERO IT OUT - The pointer indicates that we are
  262.         //   handling an event for a Floater window. 
  263.  
  264.         floaterEvent = TRUE;
  265.         }
  266.         
  267.     return(floaterEvent);
  268.     }
  269.  
  270. // * ****************************************************************************** *
  271. // * ****************************************************************************** *
  272.  
  273. // Thanks to Dair Grant (dair.grant@ucl.ac.uk) - I now check the MBarHeight
  274. //   of the *Front* process, and remember (via globals) when executing in bkgd.
  275.  
  276. // Remember that this function must be called from within that app's context!
  277. Boolean TestScreenSaver() {
  278.     Boolean inFront=FALSE;
  279.     long result;
  280.     ProcessSerialNumber frontPSN, curPSN;
  281.  
  282.     glob.blockFloats = FALSE;
  283.  
  284.     // Most screensavers should register themselves this way
  285.     if (!Gestalt('SAVR', &result) && (result & 0x02)) glob.blockFloats = TRUE;
  286.       else {
  287.         // We also want to hide ourselves if the foreground application
  288.         // has hidden the menu bar, since this implies they're taking
  289.         // over the whole screen (and they probably don't want us visible).
  290.         
  291.         // Only when we are executing in the foreground app can we check the
  292.         //   height of the menubar. When the front process has hidden its
  293.         //   menubar, then we set a global flag to enact our desires.
  294.         if (!GetFrontProcess(&frontPSN) && !GetCurrentProcess(&curPSN))
  295.             if (SameProcess(&frontPSN, &curPSN, &inFront)) inFront = FALSE;
  296.         
  297.         if (inFront && (GetMBarHeight() == 0)) glob.blockFloats = TRUE;
  298.         }
  299.     
  300.     return(glob.blockFloats);
  301.     }
  302.  
  303.  
  304.